﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading;
using System.Drawing;
using System.IO;
using System.Collections;
using BaseHelper;
using BaseHelper.Http;
using BaseHelper.Base;
using System.Collections.Concurrent;


namespace DeviceSDK.NetTraffic.Baidu
{
    public class BaiduMap_JiaoTong
    {

        private static ConcurrentDictionary<string, Thread> slThread = new ConcurrentDictionary<string, Thread>();
        //private static List<Thread> ltThread = new List<Thread>();
        private static ConcurrentDictionary<string, BaiduInfo> slList = new ConcurrentDictionary<string, BaiduInfo>();


        private static Thread threadWorking;
        private static object locker=new object();

        private static bool IsRun = false;
        //获取错误代码
        public static string Get_Error(int ret)
        {


            switch (ret)
            {
                case 0:
                    return "操作成功！";
                case 1:
                    return "操作失败！";
                case 2:
                    return "该交通ID已经存在！";

                default:
                    return "未知错误！";
            }
        }

        //设置初始化
        public static int Init()
        {
            Set_Close();
           

            IsRun = true;
            BaiduCache.Init();

            if (threadWorking == null)
            {
                threadWorking = new Thread(thCollect);
                threadWorking.Name = "DeviceSDK.NetTraffic.Baidu.BaiduMap_JiaoTong.Init().threadWorking";
                //threadWorking.IsBackground = true;
                threadWorking.Start();
                ThreadHelper.Add(threadWorking.ManagedThreadId, threadWorking.Name);
            }

            return 0;

        }

        public static int Set_Close()
        {
            IsRun = false;
            try
            {
                //foreach (Thread th in slThread.Values)
                //{
                //    try
                //    {
                //        if(th!=null)
                //            th.Abort();
                //    }
                //    catch { }
                //}

                if (threadWorking != null)
                {
                    threadWorking.Abort();
                    threadWorking = null;
                }
            }
            catch(Exception ex)
            {
                LogHelper.Err("DeviceSDK.NetTriffic.Baidu.BaiduMap_JiaoTong.cs", "Set_Close", ex);
            }
            slThread.Clear();
            slList.Clear();
            BaiduCache.Stop();
            GC.Collect();


            return 0;
        }

        #region 暂时不用
        //public static int Set_ApiListen(string CityID, string TrafficID)
        //{
        //    if (slList.ContainsKey(TrafficID))
        //    {
        //        return 2;
        //    }

        //    IsRun = true;

        //    Thread th = new Thread(new ParameterizedThreadStart(Get_TrafficeInfo));
        //    th.Name = "RT.Helper.Device.Radar.Baidu.BaiduMap_JiaoTong.SetApiListen()";
        //    th.Start(new object[] { CityID, TrafficID });
        //    sl.Add(TrafficID, th);

        //    return 0;
        //}
        
        //private static void Get_TrafficeInfo(object obj)
        //{
        //    RT.Helper.Http.HttpHelper http = new RT.Helper.Http.HttpHelper();

        //    object[] objs = (object[])obj;
        //    string CityID = (string)objs[0];
        //    string TrafficID = (string)objs[1];

        //    string Url = "https://jiaotong.baidu.com/trafficindex/city/roadcurve?cityCode=" + CityID + "&id=" + ToolsHelper.StrToUrl(TrafficID) + "&callback=ret";
        //    string LastTime = "";
        //    do
        //    {
        //        try
        //        {
        //            string Html = http.Get(Url);
        //            Regex reg = new Regex(@"\""datatime\"":\""(.*?)\"",.*?,\""speed\"":\""(\d{2})\.\d{2}\"",\""congestLength\"":\""([-|.*?])"",\""congestIndex\"":\""(.*?)\"",.*?\}", RegexOptions.Singleline);
        //            MatchCollection mcs = reg.Matches(Html);
        //            if (mcs.Count > 0)
        //            {
        //                Match mc = mcs[mcs.Count - 1];
        //                string Time = mc.Groups[1].Value;
        //                if (Time != LastTime)
        //                {
        //                    LastTime = Time;
        //                    string Speed = Convert.ToInt32(mc.Groups[2].Value).ToString();
        //                    string QunLen = mc.Groups[3].Value;
        //                    float State = Convert.ToSingle(mc.Groups[4].Value);

        //                    int Jam = 0;
        //                    if (State < 2.0f)
        //                        Jam = 1;
        //                    else if (State < 4.0f)
        //                        Jam = 2;
        //                    else if (State < 5.0f)
        //                        Jam = 3;
        //                    else
        //                        Jam = 4;


        //                    if (TrafficeApiDataArriveEvent != null)
        //                        TrafficeApiDataArriveEvent(TrafficID, Jam.ToString(), Speed, QunLen, Time);

        //                    Thread.Sleep(60000);    //60s
        //                }
        //                else
        //                    Thread.Sleep(30000);    //30s

        //            }
        //            else
        //            {
        //                if (TrafficeApiDataArriveEvent != null)
        //                    TrafficeApiDataArriveEvent(TrafficID, "0", "0", "0", "");
        //                Thread.Sleep(Config.Collect_Sleep*1000);        //10s
        //            }
        //        }
        //        catch
        //        {
        //            Thread.Sleep(30000);    //30s
        //        }
        //    } while (IsRun);
        //}
        #endregion

        public static int Set_MapPointListen(string SectionID,string MapPoint)
        {
            string ID = SectionID + MapPoint;

            
            if (slList.ContainsKey(ID))
            {
                return 2;
            }
            lock (locker)
            {
                BaiduInfo binfo = new BaiduInfo();
                binfo.SectionID = SectionID;
                binfo.MapPoint = MapPoint;

                string[] Data = MapPoint.Split(',');
                binfo.ID = ID;
                binfo.Zoom = Data[0];
                binfo.X = Data[1];
                binfo.Y = Data[2];
                binfo.TargetX = Convert.ToInt32(Data[3]);
                binfo.TargetY = Convert.ToInt32(Data[4]);

                if (!slList.ContainsKey(ID))
                    slList[ID]= binfo;
            }

            return 0;
        }
        

        public static void thCollect()
        {
            //int maxThread = 0,comCount;
            //ThreadPool.GetMaxThreads(out maxThread,out  comCount);
            //LogHelper.Debug("DeviceSDK.NetTraffic.Baidu.BaiduMap_JiaoTong.cs","thCollect()->ThreadPool.GetMaxThread("+ maxThread.ToString() +"," + comCount.ToString() +")" );
            BaiduInfo bdTmp;

            while (IsRun)
            {

                try
                {
                    lock (locker)
                    {
                        foreach (Thread th in slThread.Values)
                        {
                            try
                            {
                                if (th.IsAlive || th.ThreadState == ThreadState.Running)
                                {
                                    th.Abort();
                                }
                            }
                            catch(Exception ex2)
                            {

                                Console.WriteLine("DeviceSDK.NetTraffice.Baidu.BaiduMap_JiaoTong.cs->thCollect(ex2) " + ex2.Message);
                            }
                        }
                    }
                }
                catch(Exception ex)
                {
                    Console.WriteLine("DeviceSDK.NetTraffice.Baidu.BaiduMap_JiaoTong.cs->thCollect(ex) " + ex.Message);
                }
                     
                finally
                {
                    slThread.Clear();
                }
                GC.Collect();
              
                if (slList.Count > 0)
                {

                    try
                    {
                        lock (locker)
                        {
                            ICollection<string> keys = slList.Keys;
                            foreach (string ID in keys)
                            {
                                try
                                {
                                    if (slThread.ContainsKey(ID))
                                    {
                                        LogHelper.Debug("BaiduMap_JiaoTong.cs", "slThread.ContansKey(" + ID + ")==true");
                                        continue;
                                    }

                                    if (slList.TryGetValue(ID, out bdTmp))
                                    {
                                        Thread th = new Thread(thGet_MapPoint);
                                        
                                        th.Name = "DeviceSDK.NetTraffic.Baidu.thCollect.th.." + ID;
                                        slThread[ID] = th;

                                        //th.IsBackground = true;
                                        th.Start(bdTmp);

                                        ThreadHelper.Add(th.ManagedThreadId, th.Name);

                             
                      

                                    }
                                        
                                    #region 测试
                                    //ThreadPool.QueueUserWorkItem(
                                    //        new WaitCallback(obj =>
                                    //        {
                                    //            thGet_MapPoint(slList[ID]);
                                    //        })
                                    //    );

                                    ////如果存在thread
                                    //if (!slThread.ContainsKey(ID) || slThread[ID] == null || !slThread[ID].IsAlive)
                                    //{
                                    //    //slThread[ID] = new Thread(thGet_MapPoint);
                                    //    //slThread[ID].Name = "thBaiduMap_JiaoTong." + ID;
                                    //    //slThread[ID].IsBackground = true;
                                    //    //try
                                    //    //{
                                    //    //    slThread[ID].Start(slList[ID]);
                                    //    //}
                                    //    //catch (Exception ex4)
                                    //    //{
                                    //    //    LogHelper.Err("RT.Helper.Device.Radar.Baidu.BaiduMap_JiaoTong.cs", "thCollect->ex4,slThread:" + slThread.Count.ToString(), ex4);
                                    //    //}

                                    //}
                                    //else
                                    //{
                                    //    //已经存在了，并且是在运行处理中，跳过
                                    //}
                                    #endregion
                                }
                                catch (Exception ex2)
                                {
                                    //LogHelper.Err("RT.Helper.Device.Radar.Baidu.BaiduMap_JiaoTong.cs", "thCollect->ex2", ex2);
                                }
                            }
                        }

                    }
                    catch(Exception ex)
                    {
                        LogHelper.Err("DeviceSDK.NetTraffic.Baidu.BaiduMap_JiaoTong.cs", "thCollect()", ex);
                    }
                }

                //休眠时长
                if(DateTime.Now.Hour>=0 && DateTime.Now.Hour<6)
                    Thread.Sleep(NetTrafficHelper.Collect_Sleep * 1000 * 2);
                else
                    Thread.Sleep(NetTrafficHelper.Collect_Sleep * 1000);
            }

            ThreadHelper.Remove(Thread.CurrentThread.ManagedThreadId);


        }

        private static void thGet_MapPoint(object obj)
        {

            BaiduInfo binfo = (BaiduInfo)obj;
            
            string Url = "http://its.map.baidu.com:8002/traffic/TrafficTileService?time=1536197145990&label=web2D&v=016&level=" + binfo.Zoom + "&x=" + binfo.X + "&y=" + binfo.Y + "&scaler=1";

            try
            {
                Bitmap mapImg = BaiduCache.GetImage(Url);
                if (mapImg != null)
                {
                    #region 分析颜色
                    Color color = mapImg.GetPixel(binfo.TargetX, binfo.TargetY);

                    int R = (int)color.R;
                    int G = (int)color.G;
                    int B = (int)color.B;
                    int A = (int)color.A;

                    int Jam = 0;
                    if (A > 200)
                    {
                        if (R > 250 && G > 200 && B > 60)
                            Jam = 2;
                        else if (R > 170 && G < 5 && B < 5)
                            Jam = 4;
                        else if (R > 210 && G < 90 && B < 90)
                            Jam = 3;
                        else if (R < 90 && G > 190 && B > 100 && B < 150)
                            Jam = 1;

                    }

                    #endregion

                    NetTrafficHandler.TrafficeMapPointDataArrive(binfo.SectionID, Jam.ToString());
                }
                else
                {
                    NetTrafficHandler.TrafficeMapPointDataArrive(binfo.SectionID, "0");
                }


            }
            catch (Exception ex)
            {
                LogHelper.Err("DeviceSDK.NetTraffic.Baidu.BaiduMap_JiaoTong.cs", "thGet_MapPoint()", ex);
            }
            finally
            {
                try
                {
                    Thread th;
                    if (slThread.ContainsKey(binfo.ID))
                        slThread.TryRemove(binfo.ID,out th);
                }
                catch (Exception ex)
                {
                    LogHelper.Err("DeviceSDK.NetTraffic.Baidu.BaiduMap_JiaoTong.cs", "thGet_MapPoint(finally)", ex);
                }
            }
            ThreadHelper.Remove(Thread.CurrentThread.ManagedThreadId);
         
        }

        public static int Set_StopMapPointListen(string ID)
        {
            lock (locker)
            {
                try
                {
                    BaiduInfo bd;
                    Thread th;
                    if (slList.ContainsKey(ID))
                    {
                        slList.TryRemove(ID,out bd);
                    }
                   
                    if (slThread.ContainsKey(ID) && slThread.TryGetValue(ID,out th))
                    {
                        if (th!=null && th.IsAlive)
                            th.Abort();

                        slThread.TryRemove(ID,out th);

                    }
                

                }
                catch (Exception ex)
                {
                    Console.WriteLine("DeviceSDK.NetTraffice.Baidu.BaiduMap_JiaoTong.cs->Set_StopMapPointListen(ex) " + ex.Message);
                }
            }
            return 0;
        }

        public static string Get_Data(string CityID, string TrafficID)
        {
            HttpHelperLite http = new HttpHelperLite();

            string ret = "获取接口数据失败！";
            string Url = "https://jiaotong.baidu.com/trafficindex/city/roadcurve?cityCode=" + CityID + "&id=" + ToolsHelper.StrToUrl(TrafficID) + "&callback=ret";
            try
            {
                string Html = http.Get(Url);

                Regex reg = new Regex(@"\""datatime\"":\""(.*?)\"",.*?,\""speed\"":\""(\d{2})\.\d{2}\"",\""congestLength\"":\""([-|.*?])"",\""congestIndex\"":\""(.*?)\"",.*?\}", RegexOptions.Singleline);
                MatchCollection mcs = reg.Matches(Html);

                if (mcs.Count > 0)
                {
                    Match mc = mcs[mcs.Count - 1];
                    string Time = mc.Groups[1].Value;
                    string Speed = mc.Groups[2].Value;
                    string QunLen = mc.Groups[3].Value == "-" ? "无拥堵" : mc.Groups[3].Value;
                    string State = mc.Groups[4].Value;

                    ret = "获取接口数据成功！<br/>【时间：" + Time + "，车速：" + Speed + "km/h，拥堵长度：" + QunLen + ",拥堵值：" + State + "】";
                }

            }
            catch (Exception ex)
            {
                Console.WriteLine("DeviceSDK.NetTraffice.Baidu.BaiduMap_JiaoTong.cs->Get_Data(ex) " + ex.Message);
            }
            return ret;
        }

        public static TravelInfo Get_Travel_Time(string StartPos, string PassPos,string EndPos)
        {
            try
            {
                HttpHelperLite http = new HttpHelperLite();

                string[] sn = StartPos.Split(',');
                string[] en = EndPos.Split(',');
                string[] ps = PassPos.Split(',');
                StartPos = sn[1]+ "," + sn[0];
                EndPos = en[1] + " ," + en[0];
                //PassPos = "$$1$$%20to:1$$$$"+PassPos+"$$%E4%BA%91%E5%8D%97%E7%9C%81%E5%A4%A7%E7%90%86%E7%99%BD%E6%97%8F%E8%87%AA%E6%B2%BB%E5%B7%9E%E5%A4%A7%E7%90%86%E5%B8%82S221(%E5%A4%A7%E4%B8%BD%E7%BA%BF)$$0$$$$"; //ps[1] + "," + ps[0];
                PassPos = "";//2019.7.10 暂时屏蔽
                string Url = "https://map.baidu.com/?newmap=1&from=webmap&qt=nav&sn=$$$$" + StartPos + "$$$$0$$$$&en=$$$$" + EndPos + "$$$$0$$$$" + PassPos + "&version=4&route_traffic=1&ie=utf-8&l=17.42";
                //string Url = "https://map.baidu.com/?newmap=1&reqflag=pcmap&biz=1&from=webmap&da_par=direct&pcevaname=pc4.1&qt=nav&c=111&sn=1$$$$" + StartPos + "$$$$0$$$$&en=1$$$$" + EndPos + "$$$$0$$$$$$1$$%20to:1$$$$" + PassPos + "$$$$0$$$$&sc=111&ec=111+to:111&pn=0&rn=5&mrs=0&version=4&route_traffic=1&sy=0&da_src=&da_src=pcmappg.searchBox.button&extinfo=63&tn=B_NORMAL_MAP&nn=0&ie=utf-8&l=16";
                try
                {
                    string Html = http.Get(Url);
                    if (Html.Contains("result"))
                    {
                        Hashtable htRet = (Hashtable)JsonHelper.Decode(Html);
                        Hashtable htContent = (Hashtable)htRet["content"];
                        ArrayList alRoutes = (ArrayList)htContent["routes"];

                        if (alRoutes.Count == 0)
                        {
                            LogHelper.Err("DeviceSDK.NetTraffic.Baidu.BaiduMap_JiaoTong.cs", "Get_Travel_Time()", "alRoutes.Count==0");
                            return null;
                        }

                        Hashtable htStepsFirst = (Hashtable)alRoutes[0];
                        ArrayList alLegs = (ArrayList)htStepsFirst["legs"];
                        Hashtable htLegsFirst = (Hashtable)alLegs[0];
                        int distance = Convert.ToInt32(htLegsFirst["distance"]);
                        int duration = Convert.ToInt32(htLegsFirst["duration"]);
                    
                        //traffic_condition /= htSetp.Count; // 0： 无路况 1： 畅通 2： 缓行 3： 拥堵 4： 严重拥堵 

                        return new TravelInfo(distance, duration,0,0,0,0);//, Convert.ToInt32(traffic_condition));
                    }
                }
                catch (Exception ex)
                {
                    Console.WriteLine("DeviceSDK.NetTraffice.Baidu.BaiduMap_JiaoTong.cs->Get_Travel_Time(ex) " + ex.Message);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("DeviceSDK.NetTraffice.Baidu.BaiduMap_JiaoTong.cs->Get_Travel_Time(ex) " + ex.Message);
            }
            return null;
        }

        public static TravelInfo Get_Travel_Time_Api(string StartPos, string PassPos, string EndPos, string Tactics="0")
        {
           HttpHelperLite http = new HttpHelperLite();
  
            //string Url = "http://api.map.baidu.com/directionlite/v1/driving?origin=" + StartPos + "&destination=" + EndPos + "&waypoints=" +PassPos +"&ak=" + RadarHelper.Api_Key_Baidu;

           string Url = "http://api.map.baidu.com/direction/v2/driving?origin=" + StartPos + "&destination=" + EndPos + "&waypoints=" + PassPos + "&tactics=" + Tactics + "&ak=" + NetTrafficHelper.Api_Key_Baidu;
           
            try
            {
                string Html = http.Get(Url);
                if(Html.Contains("status"))
                {

                    Hashtable htRet=(Hashtable)JsonHelper.Decode(Html);
                    if (htRet["status"].ToString() != "0")
                    {
                        LogHelper.Err("DeviceSDK.NetTraffic.Baidu.BaiduMap_JiaoTong.cs", "Get_Travel_Time()", Html);
                        return null;
                    }
                    if (htRet["message"].ToString() != "ok" && htRet["message"].ToString() != "成功")
                        return null;

                    
                    Hashtable htResult=(Hashtable)htRet["result"];
                    ArrayList htRoutes=(ArrayList)htResult["routes"];
                    Hashtable htFirstRoutes=(Hashtable)htRoutes[0];
                    ArrayList htSetp = (ArrayList)htFirstRoutes["steps"];



                    int total_distance = Convert.ToInt32(htFirstRoutes["distance"]);
                    int total_duration = Convert.ToInt32(htFirstRoutes["duration"]);

                    float base_distance = 0;
                    float real_distance = 0;

                    int max_jam = -1;
                    int first_jam=-1;
                    float first_distance =-1;
                    float max_distance = -1;

                    List<SectionInfo> lt = new List<SectionInfo>();
                    string steps = "";

                    for (int i = 0; i < htSetp.Count; i++)
                    {
                        Hashtable ht = (Hashtable)htSetp[i];
                        real_distance +=Convert.ToSingle(ht["distance"].ToString());
                    }

                    for(int i=0;i<htSetp.Count;i++)
                    {
                        Hashtable ht=(Hashtable)htSetp[i];
                        ArrayList alConditions = (ArrayList)ht["traffic_condition"];

                        steps += ht["path"].ToString();

                        if (i < (htSetp.Count - 1))
                            steps += ";";

                        
                        foreach(Hashtable condition in alConditions)
                        {
                            int step_jam = Convert.ToInt32(condition["status"].ToString());
                            float step_distance = Convert.ToSingle(condition["distance"].ToString());

                            
                            if (step_jam == 4)
                                step_jam = 3;

                            if (step_jam > max_jam)
                            {
                                max_jam = step_jam;
                                max_distance = Convert.ToInt32(base_distance);
                            }

                            if (first_jam < 3)
                            {
                                //if (first_jam !=3 && step_jam == 3)
                                if (first_jam < 2 && step_jam == 3)
                                {
                                    first_jam = 3;
                                    first_distance =Convert.ToInt32(base_distance);
                                }
                                else if (first_jam < 2 && step_jam == 2)
                                {
                                    first_jam = 2;
                                    first_distance = Convert.ToInt32(base_distance);
                                }
                            }

                            float percent = step_distance / real_distance;

                            lt.Add(new SectionInfo(Convert.ToInt32(base_distance), Convert.ToInt32(step_distance), step_jam, percent));

                            base_distance += step_distance;

                        }
                     
                        //traffic_condition += Convert.ToInt32((Hashtable)(((ArrayList)ht["traffic_condition"])[0])["status"]);
                    }
           
                    //Hashtable htStepsFirst = (Hashtable)htRoutes[0];
                    //traffic_condition /= htSetp.Count; // 0： 无路况 1： 畅通 2： 缓行 3： 拥堵 4： 严重拥堵 

                    return new TravelInfo(total_distance, total_duration, first_jam,first_distance, max_jam,max_distance,steps, lt.ToArray());//, Convert.ToInt32(traffic_condition));
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("DeviceSDK.NetTraffice.Baidu.BaiduMap_JiaoTong.cs->Get_Travel_Time_Api(ex) " + ex.Message);
            }
            return null;
        }

    }

}
